﻿using AutoMapper;
using PowerHub.MES.Common.NumberingCenter;
using PowerHub.MES.DTO.Crew.DTO;
using PowerHub.MES.DTO.Crew.QueryDto;
using PowerHub.MES.EFBase;
using PowerHub.MES.Entities.Crew;
using PowerHub.MES.Entities;
using PowerHub.MES.IRepository.ICrew;
using PowerHub.MES.IServices.ICrew;
using PowerHub.MES.Jwt;
using PowerHub.MES.ReturnEntity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PowerHub.MES.IServices.IProduction;
using PowerHub.MES.Entities.Production;
using PowerHub.MES.DTO.Production.QueryDTO;
using PowerHub.MES.DTO.Production.DTO;
using PowerHub.MES.IRepository.IProduction;
using Microsoft.IdentityModel.Tokens;

namespace PowerHub.MES.Services.Production
{
    /// <summary>
    /// 生产任务接口实现层
    /// </summary>
    public class Production_ProductionTaskServices : BaseServices<Production_ProductionTask>, IProduction_ProductionTaskServices
    {
        private IProduction_ProductionTaskRepository _iProduction_ProductionTaskRepository;
        private ICrew_SchedulingPlanDetialRepository _SchedulingPlanDetialRepository;
        public UserServices _userServices;
        private IMapper _mapper;
        private static Random random = new Random();

        public Production_ProductionTaskServices(PowerHubMesContext powerHubMesContext, IProduction_ProductionTaskRepository iProduction_ProductionTaskRepository,
            UserServices userServices, IMapper mapper, ICrew_SchedulingPlanDetialRepository schedulingPlanDetialRepository) : base(powerHubMesContext)
        {
            _iProduction_ProductionTaskRepository = iProduction_ProductionTaskRepository;
            _userServices = userServices;
            _mapper = mapper;
            _SchedulingPlanDetialRepository = schedulingPlanDetialRepository;
        }

        /// <summary>
        /// 获取生产任务列表
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<OperationPageResult<List<Production_ProductionTask>>> GetProduction_ProductionTaskPageListAsync(QueryProduction_ProductionTaskDTO query)
        {
            return await _iProduction_ProductionTaskRepository.GetProduction_ProductionTaskPageListAsync(query);
        }

        /// <summary>
        /// 添加生产任务
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<OperationResult<bool>> CreateProduction_ProductionTaskAsync(Production_ProductionTaskDTO query)
        {
            var ProductionTasks = new List<Production_ProductionTask>();

            //判断工单
            if (string.IsNullOrEmpty(query.WorkOrderId))
            {
                throw new Exception("请先选择工单！");
            }

            //判断计划明细
            if (query.SchedulingPlanDetials.Count < 1)
            {
                throw new Exception("计划不可为空！");
            }

            //判断计划明细是否分配任务
            foreach (var item in query.SchedulingPlanDetials)
            {
                var Production_ProductionTask = new Production_ProductionTask();
                if (string.IsNullOrEmpty(item.ProductionTaskName))
                {
                    throw new Exception($"工作站台：{item.WorkStation.WorkStationName} 还没有分配任务！");
                }
                if (item.SchedulingQuantity < 1)
                {
                    throw new Exception($"工作站台：{item.WorkStation.WorkStationName} 还没有分配任务数量！");
                }
                Production_ProductionTask.Id = Guid.NewGuid().ToString();
                Production_ProductionTask.ProductionTaskNO = GenerateBasicDataNO.GenerateTaskNO();
                Production_ProductionTask.WorkOrderId = query.WorkOrderId;
                Production_ProductionTask.ProductionTaskName = $"{item.ProductionTaskName}[ {item.SchedulingQuantity} ]";
                Production_ProductionTask.SchedulingPlanId = item.Crew_SchedulingPlanId;
                //Production_ProductionTask.ProductBillId = item.ProductBillId;
                Production_ProductionTask.WorkStationId = item.WorkStationId;
                Production_ProductionTask.UserinfoId = item.UserinfoId;
                Production_ProductionTask.ProcessId = item.WorkStation.ProcessId;
                Production_ProductionTask.Status = 0;
                ProductionTasks.Add(Production_ProductionTask);
            }


            return await _iProduction_ProductionTaskRepository.CreateProduction_ProductionTaskAsync(ProductionTasks);
        }


        /// <summary>
        /// 批量删除生产任务
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<OperationResult<bool>> DeletionProduction_ProductionTaskAsync(List<string>? ids)
        {
            if (ids.Count < 1)
            {
                throw new Exception("请先选择数据！");
            }
            return await _iProduction_ProductionTaskRepository.DeletionProduction_ProductionTaskAsync(ids);
        }


        /// <summary>
        /// 更新生产任务
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<OperationResult<bool>> UpdateProduction_ProductionTaskAsync(Production_ProductionTaskDTO query)
        {
            if (query == null)
            {
                throw new Exception("请先选择数据！");
            }

            //根据id获取生产任务信息
            Production_ProductionTask Production_ProductionTask = await GetEntityAsync(d => d.Id.Equals(query.Id));
            if (Production_ProductionTask == null)
            {
                throw new Exception("更新生产任务信息发生了异常,请刷新页面后试试");
            }
            Production_ProductionTask.Updator = _userServices.UserName;

            return await _iProduction_ProductionTaskRepository.UpdateProduction_ProductionTaskAsync(Production_ProductionTask);

        }

        /// <summary>
        /// 根据计划明细id添加生产任务（单）
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task<OperationResult<bool>> CreateProduction_ProductionTaskBySchedulingPlanDetialIdAsync(Production_ProductionTaskByDetialDTO query)
        {
            #region 校验

            //判断工单
            if (string.IsNullOrEmpty(query.WorkOrderId))
            {
                throw new Exception("请先选择工单！");
            }


            //判断任务
            if (string.IsNullOrEmpty(query.MaterialId) || string.IsNullOrEmpty(query.ProductionTaskName))
            {
                throw new Exception("找不到任务信息，请联系管理员！");
            }
            if (query.SchedulingQuantity < 1)
            {
                throw new Exception("请输入分配数量！");
            }

            //获取工单BOm
            var billOfMaterials = await _iProduction_ProductionTaskRepository.GetProduction_BillOfMaterialsByIdAsync(query.billOfMaterialId);
            if (billOfMaterials == null)
            {
                throw new Exception("找不到工单BOM信息，请联系管理员！");
            }
            //可分配数量 
            var distributableQuantity = billOfMaterials.PredictQuantity - billOfMaterials.AllocatedQuantity;
            if (query.SchedulingQuantity > distributableQuantity)
            {
                throw new Exception("当前输入分配任务量大于现在可以分配数量，请检查后重试！");
            }


            //获取排班计划明细
            var schedulingPlanDetial = await _SchedulingPlanDetialRepository.GetCrew_SchedulingPlanDetialByIdAsync(query.Id);
            if (schedulingPlanDetial == null)
            {
                throw new Exception("找不到当前人员信息，请联系管理员！");
            }

            #endregion


            var production_ProductionTask = new Production_ProductionTask();
            bool isUpdate = true;
            //判断是否已分配任务
            if (schedulingPlanDetial.ProductionTask != null)
            {
                if ((query.SchedulingQuantity - schedulingPlanDetial.ProductionTask.SchedulingQuantity) == 0)
                {
                    throw new Exception("分配数量不能相同,请重新设置！");
                }
                schedulingPlanDetial.ProductionTask.SchedulingQuantity = query.SchedulingQuantity - schedulingPlanDetial.ProductionTask.SchedulingQuantity;

                //更新工单BOM已分配数量
                billOfMaterials.AllocatedQuantity += schedulingPlanDetial.ProductionTask.SchedulingQuantity;
                schedulingPlanDetial.SchedulingQuantity += schedulingPlanDetial.ProductionTask.SchedulingQuantity;
                isUpdate = false;
            }
            else
            {
                production_ProductionTask.Id = Guid.NewGuid().ToString();
                production_ProductionTask.ProductionTaskNO = GenerateBasicDataNO.GenerateTaskNO();
                production_ProductionTask.WorkOrderId = query.WorkOrderId;
                production_ProductionTask.ProductionTaskName = $"{query.ProductionTaskName}[ {query.SchedulingQuantity} ]";
                production_ProductionTask.MaterialId = query.MaterialId;
                production_ProductionTask.SchedulingQuantity = query.SchedulingQuantity;
                production_ProductionTask.SchedulingPlanId = schedulingPlanDetial.Crew_SchedulingPlanId;
                production_ProductionTask.WorkStationId = schedulingPlanDetial.WorkStationId;
                production_ProductionTask.UserinfoId = schedulingPlanDetial.UserinfoId;
                production_ProductionTask.ProcessId = schedulingPlanDetial.WorkStation != null ? schedulingPlanDetial.WorkStation.ProcessId : null;
                production_ProductionTask.Status = 0;

                //更新工单BOM已分配数量
                billOfMaterials.AllocatedQuantity += query.SchedulingQuantity;

                //排班明细
                schedulingPlanDetial.ProductionTaskId = production_ProductionTask.Id;
                schedulingPlanDetial.SchedulingQuantity = query.SchedulingQuantity;
            }
            schedulingPlanDetial.MaterialId = query.MaterialId;

            return await _iProduction_ProductionTaskRepository.CreateProduction_ProductionTaskBySchedulingPlanDetialIdAsync(isUpdate, production_ProductionTask, schedulingPlanDetial, billOfMaterials);

        }
    }
}
